Pony vs O-CPS

$ cat main.pony use "time" actor Main fun factorial(x: I64): I64 => if x == 0 then 1 else x * factorial(x - 1) end fun ack(m: I64, n: I64): I64 => if m == 0 then n + 1 else if n == 0 then ack(m - 1, 1) else ack(m - 1, ack(m, n - 1)) end end new create(env: Env) => let axs: U64 = Time.nanos() let a: I64 = ack(3,4) let axe: U64 = Time.nanos() let fs: U64 = Time.nanos() let f: I64 = factorial(5) let fe: U64 = Time.nanos() let fac: U64 = fe - fs let akk: U64 = axe - axs env.out.print("Ackerman: " + fac.string() + "ns, " + a.string()) env.out.print("Factorial: " +akk.string() + "ns, " + f.string()) $ ponyc $ ./voxoz Ackerman: 80332ns, 125 Factorial: 291ns, 120

В то время как у нас:

#[bench] fn fac_rec<'a>(b: &'a mut Bencher) { let h = handle::new(Interpreter::new().unwrap()); let eval = &"fac:{$[x=1;1;x*fac[x-1]]}".to_string(); let mut code = h.borrow_mut().parse(eval); h.borrow_mut().run(code).unwrap(); let f = h.borrow_mut().parse(&"fac[5]".to_string()); b.iter(|| { h.borrow_mut().run(f); h.borrow_mut().gc(); }) } #[bench] fn akkerman_k<'a>(b: &'a mut Bencher) { let h = handle::new(Interpreter::new().unwrap()); h.borrow_mut().define_primitives(); let akk = h.borrow_mut().parse(&"f:{[x;y]$[0=x;1+y;$[0=y;f[x-1;1];f[x-1;f[x;y-1]]]]}".to_s tring()); h.borrow_mut().run(akk).unwrap(); let call = h.borrow_mut().parse(&"f[3;4]".to_string()); b.iter(|| { h.borrow_mut().run(call); h.borrow_mut().gc(); }) } test akkerman_k ... bench: 442 ns/iter (+/- 37) test fac_rec ... bench: 195 ns/iter (+/- 55)